package com.example.demo.aspect;

import com.example.demo.Utils.GetRequestIpUtil;
import com.example.demo.dao.LogDao;

import com.example.demo.pojo.Admin;
import com.example.demo.pojo.Log;
import jdk.internal.org.objectweb.asm.tree.LocalVariableAnnotationNode;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.xml.ws.spi.http.HttpContext;
import java.lang.reflect.Method;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * Created by hasee
 * on 2019/12/7 10:12
 */
@Aspect
@Component
public class LogAspect {

    @Autowired
    private LogDao logDao;

    @Pointcut("@annotation(com.example.demo.custom_annotation.Log)")
    public void pointcut(){ }

    @Around("pointcut()")
    public Object arount(ProceedingJoinPoint point){
        System.out.println("LogAspect执行...");
        Object result = null;
        long beginTime = System.currentTimeMillis();
        try{
            //执行
            result = point.proceed();
        }catch (Throwable e){
            e.printStackTrace();
        }
        //执行时长（毫秒）
        long time = System.currentTimeMillis();
        System.out.println("当前系统时间："+System.currentTimeMillis()+"\t"+"开始时间："+beginTime);
        //保存日志
        saveLog(point,time);
        return result;
    }

    private void saveLog(ProceedingJoinPoint point,long time){
        //根据logAnnotation.value()的值，即注解在不同方法上设置的值，结合正则表达式判断operationType
        String infoPattern = ".*登录.*";
        String successPattern = ".*确定.*";
        String warningPattern = ".*修改.*";
        String dangerPattern = ".*禁止.*";
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        //Log基础类
        Log log = new Log();
        //Log注解类
        com.example.demo.custom_annotation.Log logAnnotation = method.getAnnotation(com.example.demo.custom_annotation.Log.class);
        if(logAnnotation != null){
            //注解的描述
            log.setRecordOperation(logAnnotation.value());
            //正则判断
            if(Pattern.matches(infoPattern,logAnnotation.value())){
                log.setOperationType("info");
            }
            if(Pattern.matches(successPattern,logAnnotation.value())){
                log.setOperationType("success");
            }
            if(Pattern.matches(warningPattern,logAnnotation.value())){
                log.setOperationType("warning");
            }
            if(Pattern.matches(dangerPattern,logAnnotation.value())){
                log.setOperationType("danger");
            }
        }
        //请求的方法名
        String className = point.getTarget().getClass().getName();
        String methodName = signature.getName();
        log.setMethod(className + "." + methodName + "()");
        //请求的方法参数值
        Object[] args = point.getArgs();
        //请求的方法参数名称
        LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
        String[] paramNames = u.getParameterNames(method);

        List arrayList =new ArrayList<>();
        Admin admin = new Admin();
        //判断参数和参数名不为空
        if(args != null && paramNames != null){
            String params = "";
            //循环每一个参数到params
            for(int i = 0;i<args.length;i++){
                params += "\t" + paramNames[i] + ":" + args[i];
                arrayList.add(args[i]);
            }
            admin = (Admin)arrayList.get(0);
            System.out.println("admin对象内容为："+admin+admin.getAdminAccount());
            //将所有params赋予log基础类的params
            System.out.println("参数："+params);
            log.setParams(params);
        }
        //获取httpRequest
        HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
        //设置IP地址
        log.setIp(GetRequestIpUtil.getIpAddr(request));
        //保存时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//时间格式
        Date nowDate = new Date(time);//得到当前时间
        String date = sdf.format(nowDate );
        System.out.println("当前时间："+nowDate+date);
        log.setCreateTime(date);
        //获取注解的内容

        //保存管理员账号
        log.setAdminAccount(admin.getAdminAccount());
        //保存系统日志
        logDao.saveLog(log);

    }
}
